package strs

import (
	"math"
	"strconv"
	"strings"
)

func ParseBytes(s string) uint64 {
	s = strings.ReplaceAll(s, " ", "")
	n, e := strconv.ParseUint(s, 10, 0)
	if e == nil {
		return n
	}
	nums := strings.Split(s, "*")
	if len(nums) > 1 {
		size := uint64(1)
		for _, num := range nums {
			n, err := strconv.ParseUint(num, 10, 0)
			if err != nil {
				return 0
			}
			size *= n
		}
		return size
	}
	ss := strings.ToUpper(s)
	bs := []byte(ss)
	size := uint64(0)
	i := 0
	for ; i < len(bs); i++ {
		if bs[i] >= '0' && bs[i] <= '9' {
			size = size*10 + uint64(bs[i]-'0')
		} else {
			break
		}
	}
	const KB = 1024
	const MB = KB * 1024
	const GB = MB * 1024
	const TB = GB * 1024
	const PB = TB * 1024
	const EB = PB * 1024
	hasB := false
	if i < len(bs) {
		switch bs[i] {
		case 'B':
			hasB = true
		case 'K':
			if size < math.MaxUint64/KB {
				size *= KB
			} else {
				return 0
			}
		case 'M':
			if size < math.MaxUint64/MB {
				size *= MB
			} else {
				return 0
			}
		case 'G':
			if size < math.MaxUint64/GB {
				size *= GB
			} else {
				return 0
			}
		case 'T':
			if size < math.MaxUint64/TB {
				size *= TB
			} else {
				return 0
			}
		case 'P':
			if size < math.MaxUint64/PB {
				size *= PB
			} else {
				return 0
			}
		case 'E':
			if size < math.MaxUint64/EB {
				size *= EB
			} else {
				return 0
			}
		default:
			return 0
		}
	} else {
		return size
	}
	i++
	if i < len(bs) {
		//byte
		if !hasB {
			if bs[i] != 'B' {
				return 0
			}
			i++
			if i == len(bs) {
				return size
			}
			hasB = true
		}
		if hasB && i+3 == len(bs) && bs[i] == 'Y' && bs[i+1] == 'T' && bs[i+2] == 'E' {
			return size
		}
	} else {
		return size
	}
	return 0
}
